using GroupSix.Application.Dtos;
using GroupSix.Domain.Repositories;
using GroupSix.Domain.Entity.App;

namespace GroupSix.Application.Services;

/// <summary>
/// 权限控制服务
/// </summary>
public class PermissionService
{
    private readonly IUserRepository _userRepository;
    private readonly IRoleRepository _roleRepository;
    private readonly IMenuRepository _menuRepository;

    public PermissionService(
        IUserRepository userRepository,
        IRoleRepository roleRepository,
        IMenuRepository menuRepository)
    {
        _userRepository = userRepository;
        _roleRepository = roleRepository;
        _menuRepository = menuRepository;
    }

    /// <summary>
    /// 获取用户权限
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <returns>用户权限信息</returns>
    public async Task<(bool success, string message, UserPermissionsResponseDto? data)> GetUserPermissionsAsync(GetUserPermissionsRequestDto request)
    {
        try
        {
            // 获取用户信息
            var user = await _userRepository.GetByIdAsync(request.UserId);
            if (user == null)
            {
                return (false, "用户不存在", null);
            }

            // 获取用户角色（只获取未删除的角色）
            var userRoles = await _userRepository.GetUserRolesAsync(request.UserId);
            var roleDtos = userRoles
                .Where(ur => ur.Role != null && !ur.Role.IsDeleted) // 确保角色存在且未删除
                .Select(ur => new UserRoleDto
                {
                    Id = ur.Role!.Id,
                    Name = ur.Role!.Name,
                    Description = ur.Role!.Description
                })
                .ToList();

            // 获取用户可访问的菜单
            var userMenus = await GetUserAccessibleMenusAsync(request.UserId);

            var response = new UserPermissionsResponseDto
            {
                UserId = user.Id,
                Username = user.Username,
                Roles = roleDtos,
                Menus = userMenus.Select(m => new MenuPermissionDto
                {
                    Id = m.Id,
                    Menuname = m.Menuname,
                    MenuPath = m.MenuPath,
                    MenuIcon = m.MenuIcon,
                    ParentId = m.ParentId,
                    Order = m.Order,
                    PermissionKey = m.PermissionKey,
                    HasAccess = true
                }).ToList()
            };

            return (true, "获取用户权限成功", response);
        }
        catch (Exception ex)
        {
            return (false, $"获取用户权限失败: {ex.Message}", null);
        }
    }

    /// <summary>
    /// 验证用户权限
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <returns>权限验证结果</returns>
    public async Task<(bool success, string message, ValidatePermissionResponseDto? data)> ValidatePermissionAsync(ValidatePermissionRequestDto request)
    {
        try
        {
            // 获取用户信息
            var user = await _userRepository.GetByIdAsync(request.UserId);
            if (user == null)
            {
                return (false, "用户不存在", null);
            }

            // 获取用户角色（只获取未删除的角色）
            var userRoles = await _userRepository.GetUserRolesAsync(request.UserId);
            var roleNames = userRoles
                .Where(ur => ur.Role != null && !ur.Role.IsDeleted) // 确保角色存在且未删除
                .Select(ur => ur.Role!.Name)
                .ToList();

            // 检查超级管理员权限
            if (roleNames.Contains("超级管理员"))
            {
                return (true, "超级管理员拥有所有权限", new ValidatePermissionResponseDto
                {
                    HasPermission = true,
                    Message = "超级管理员拥有所有权限",
                    UserRoles = roleNames
                });
            }

            // 验证具体权限
            var hasPermission = await CheckUserPermissionAsync(request.UserId, request.PermissionKey, request.MenuPath);

            var response = new ValidatePermissionResponseDto
            {
                HasPermission = hasPermission,
                Message = hasPermission ? "权限验证通过" : "权限不足",
                UserRoles = roleNames
            };

            return (true, "权限验证完成", response);
        }
        catch (Exception ex)
        {
            return (false, $"权限验证失败: {ex.Message}", null);
        }
    }

    /// <summary>
    /// 获取用户菜单
    /// </summary>
    /// <param name="request">请求参数</param>
    /// <returns>用户菜单树</returns>
    public async Task<(bool success, string message, UserMenusResponseDto? data)> GetUserMenusAsync(GetUserMenusRequestDto request)
    {
        try
        {
            // 获取用户信息
            var user = await _userRepository.GetByIdAsync(request.UserId);
            if (user == null)
            {
                return (false, "用户不存在", null);
            }

            // 获取用户可访问的菜单
            var userMenus = await GetUserAccessibleMenusAsync(request.UserId);
            
            // 构建菜单树
            var menuTree = BuildMenuTree(userMenus);

            var response = new UserMenusResponseDto
            {
                UserId = user.Id,
                Username = user.Username,
                MenuTree = menuTree,
                TotalCount = menuTree.Count
            };

            return (true, "获取用户菜单成功", response);
        }
        catch (Exception ex)
        {
            return (false, $"获取用户菜单失败: {ex.Message}", null);
        }
    }

    /// <summary>
    /// 获取用户可访问的菜单
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>可访问的菜单列表</returns>
    private async Task<List<GsMenu>> GetUserAccessibleMenusAsync(Guid userId)
    {
        // 获取用户角色（只获取未删除的角色）
        var userRoles = await _userRepository.GetUserRolesAsync(userId);
        var roleIds = userRoles
            .Where(ur => ur.Role != null && !ur.Role.IsDeleted) // 确保角色存在且未删除
            .Select(ur => ur.RoleId)
            .ToList();

        if (!roleIds.Any())
        {
            return new List<GsMenu>();
        }

        // 获取角色关联的菜单
        var roleMenus = await _roleRepository.GetRoleMenusAsync(roleIds);
        var menuIds = roleMenus.Select(rm => rm.MenuId).Distinct().ToList();

        if (!menuIds.Any())
        {
            return new List<GsMenu>();
        }

        // 获取菜单详情
        var menus = new List<GsMenu>();
        foreach (var menuId in menuIds)
        {
            var menu = await _menuRepository.GetByIdAsync(menuId);
            if (menu != null && !menu.IsDeleted)
            {
                menus.Add(menu);
            }
        }

        return menus.OrderBy(m => m.Order).ToList();
    }

    /// <summary>
    /// 检查用户是否有特定权限
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="permissionKey">权限标识</param>
    /// <param name="menuPath">菜单路径</param>
    /// <returns>是否有权限</returns>
    private async Task<bool> CheckUserPermissionAsync(Guid userId, string permissionKey, string? menuPath = null)
    {
        // 获取用户可访问的菜单
        var userMenus = await GetUserAccessibleMenusAsync(userId);

        // 检查权限标识
        if (!string.IsNullOrEmpty(permissionKey))
        {
            var hasPermission = userMenus.Any(m => 
                !string.IsNullOrEmpty(m.PermissionKey) && 
                m.PermissionKey.Equals(permissionKey, StringComparison.OrdinalIgnoreCase));
            
            if (hasPermission)
            {
                return true;
            }
        }

        // 检查菜单路径
        if (!string.IsNullOrEmpty(menuPath))
        {
            var hasMenuAccess = userMenus.Any(m => 
                !string.IsNullOrEmpty(m.MenuPath) && 
                m.MenuPath.Equals(menuPath, StringComparison.OrdinalIgnoreCase));
            
            if (hasMenuAccess)
            {
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// 构建菜单树
    /// </summary>
    /// <param name="menus">菜单列表</param>
    /// <returns>菜单树</returns>
    private List<MenuPermissionDto> BuildMenuTree(List<GsMenu> menus)
    {
        var menuDict = menus.ToDictionary(m => m.Id);
        var rootMenus = new List<MenuPermissionDto>();

        foreach (var menu in menus)
        {
            var menuDto = new MenuPermissionDto
            {
                Id = menu.Id,
                Menuname = menu.Menuname,
                MenuPath = menu.MenuPath,
                MenuIcon = menu.MenuIcon,
                ParentId = menu.ParentId,
                Order = menu.Order,
                PermissionKey = menu.PermissionKey,
                HasAccess = true,
                Children = new List<MenuPermissionDto>()
            };

            if (menu.ParentId == null)
            {
                // 根菜单
                rootMenus.Add(menuDto);
            }
            else if (menuDict.ContainsKey(menu.ParentId.Value))
            {
                // 子菜单
                var parentDto = FindMenuDtoInTree(rootMenus, menu.ParentId.Value);
                if (parentDto != null)
                {
                    parentDto.Children.Add(menuDto);
                }
            }
        }

        return rootMenus.OrderBy(m => m.Order).ToList();
    }

    /// <summary>
    /// 在菜单树中查找指定ID的菜单
    /// </summary>
    /// <param name="menuTree">菜单树</param>
    /// <param name="menuId">菜单ID</param>
    /// <returns>菜单DTO</returns>
    private MenuPermissionDto? FindMenuDtoInTree(List<MenuPermissionDto> menuTree, Guid menuId)
    {
        foreach (var menu in menuTree)
        {
            if (menu.Id == menuId)
            {
                return menu;
            }

            var found = FindMenuDtoInTree(menu.Children, menuId);
            if (found != null)
            {
                return found;
            }
        }

        return null;
    }
} 